package top.guoziyang.mydb.backend.dm.page;

import java.util.Arrays;

import top.guoziyang.mydb.backend.dm.pageCache.PageCache;
import top.guoziyang.mydb.backend.utils.RandomUtil;

/**
 * 特殊管理第一页
 * ValidCheck
 * db启动时给100~107字节处填入一串随机字节，db关闭时将其拷贝到108~115字节
 * 数据库在每次启动时，就会检查第一页两处的字节是否相同，以此来判断上一次是否正常关闭。如果是异常关闭，就需要执行数据的恢复流程。
 */
public class PageOne {
    private static final int OF_VC = 100; //表示校验码的偏移量，从第100个字节开始存储校验码。
    private static final int LEN_VC = 8; //表示校验码的长度为8字节

    /**
     * 初始化一个新的页面，大小为8KB
     * 通过setVcOpen(raw)给第一页设置一个“打开”状态的验证码。
     * */
    public static byte[] InitRaw() {
        byte[] raw = new byte[PageCache.PAGE_SIZE];
        setVcOpen(raw);
        return raw;
    }

    public static void setVcOpen(Page pg) {
        pg.setDirty(true);
        setVcOpen(pg.getData());
    }

    /**
     * 设置“打开校验码”，用于标识页面打开状态
     * 将从位置 100 开始生成的 8 字节随机数据填入raw字节数据库中，作为打开状态的校验码。
     * src：源备份，即要复制的数据源。
     * srcPos：源备份的起始复制位置。
     * dest：目标数据库，即数据要被复制到的数据库。
     * destPos：目标队列的起始粘贴位置。
     * length：要复制的长度。
     * */
    private static void setVcOpen(byte[] raw) {
        System.arraycopy(RandomUtil.randomBytes(LEN_VC), 0, raw, OF_VC, LEN_VC);
    }

    public static void setVcClose(Page pg) {
        pg.setDirty(true);
        setVcClose(pg.getData());
    }

    /**
     * 在数据库正常关闭时，会将这串字节，拷贝到第一页的 108 ~ 115 字节。
     * */
    private static void setVcClose(byte[] raw) {
        System.arraycopy(raw, OF_VC, raw, OF_VC+LEN_VC, LEN_VC);
    }

    public static boolean checkVc(Page pg) {
        return checkVc(pg.getData());
    }

    /**
     * 校验字节：
     * */
    private static boolean checkVc(byte[] raw) {
        return Arrays.equals(Arrays.copyOfRange(raw, OF_VC, OF_VC+LEN_VC), Arrays.copyOfRange(raw, OF_VC+LEN_VC, OF_VC+2*LEN_VC));
    }
}
